import Blockly from 'blockly/core'
import 'blockly/python_compressed'
import 'blockly/blockly_compressed'
import 'blockly/blocks_compressed'

Blockly.Blocks.ast_DictItem = {
  init: function () {
    this.appendValueInput('KEY').setCheck(null)
    this.appendValueInput('VALUE').setCheck(null).appendField(':')
    this.setInputsInline(true)
    this.setOutput(true, 'DictPair')
    this.setColour(15)
  }
}

Blockly.Blocks.ast_Dict = {
  init: function () {
    this.setColour(15)
    this.itemCount_ = 3
    this.setOutput(true, 'Dict')
    this.setMutator(new Blockly.Mutator(['ast_Dict_create_with_item']))
    this.updateShape_()
  },
  mutationToDom: function () {
    const container = document.createElement('mutation')
    container.setAttribute('items', this.itemCount_)
    return container
  },
  domToMutation: function (xmlElement) {
    this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10)
    this.updateShape_()
  },
  decompose: function (workspace) {
    const containerBlock = workspace.newBlock('ast_Dict_create_with_container')
    containerBlock.initSvg()
    let connection = containerBlock.getInput('STACK').connection
    let i = 0
    while (i < this.itemCount_) {
      const itemBlock = workspace.newBlock('ast_Dict_create_with_item')
      itemBlock.initSvg()
      connection.connect(itemBlock.previousConnection)
      connection = itemBlock.nextConnection
      i++
    }
    return containerBlock
  },
  compose: function (containerBlock) {
    let itemBlock = containerBlock.getInputTargetBlock('STACK')
    // Count number of inputs.
    const connections = []
    while (itemBlock && !itemBlock.isInsertionMarker()) {
      connections.push(itemBlock.valueConnection_)
      itemBlock =
        itemBlock.nextConnection && itemBlock.nextConnection.targetBlock()
    }
    // eslint-disable-next-line no-var
    for (var i = 0; i < this.itemCount_; i++) {
      const connection = this.getInput('ADD' + i).connection.targetConnection
      if (connection && connections.indexOf(connection) === -1) {
        connection.disconnect()
      }
    }
    this.itemCount_ = connections.length
    this.updateShape_()
    // eslint-disable-next-line no-var, no-redeclare
    for (var i = 0; i < this.itemCount_; i++) {
      Blockly.Mutator.reconnect(connections[i], this, 'ADD' + i)
    }
  },

  saveConnections: function (containerBlock) {
    let itemBlock = containerBlock.getInputTargetBlock('STACK')
    let index = 0
    while (itemBlock) {
      const inputs = this.getInput('ADD' + index)
      itemBlock.valueConnection_ = inputs && inputs.connection.targetConnection
      index++
      itemBlock =
        itemBlock.nextConnection && itemBlock.nextConnection.targetBlock()
    }
  },
  updateShape_: function () {
    // change blockform according to different itemCount_
    if (this.itemCount_ && this.getInput('EMPTY')) {
      this.removeInput('EMPTY')
    } else if (!this.itemCount_ && !this.getInput('EMPTY')) {
      this.appendDummyInput('EMPTY').appendField('empty dictionary')
    }
    // eslint-disable-next-line no-var
    let rep = 0
    for (let i = 0; i < this.itemCount_; i++) {
      if (!this.getInput('ADD' + i)) {
        const input = this.appendValueInput('ADD' + i).setCheck('DictPair')
        if (i === 0) {
          input.appendField('create dict with')
        }
      }
      rep = i
    }
    // Remove deleted inputs.
    rep++
    while (this.getInput('ADD' + rep)) {
      this.removeInput('ADD' + rep)
      rep++
    }
  }
}

Blockly.Blocks.ast_Dict_create_with_container = {
  init: function () {
    this.setColour(15)
    this.appendDummyInput().appendField('Add new dict elements below')
    this.appendStatementInput('STACK')
    this.contextMenu = false
  }
}

Blockly.Blocks.ast_Dict_create_with_item = {
  init: function () {
    this.setColour(15)
    this.appendDummyInput().appendField('Element')
    this.setPreviousStatement(true)
    this.setNextStatement(true)
    this.contextMenu = false
  }
}

Blockly.Python.ast_Dict = function (block) {
  // Create a dict with any number of elements of any type.
  const elements = new Array(block.itemCount_)
  for (let i = 0; i < block.itemCount_; i++) {
    const child = block.getInputTargetBlock('ADD' + i)
    if (child === null || child.type !== 'ast_DictItem') {
      elements[i] = Blockly.Python.blank + ': ' + Blockly.Python.blank
      continue
    }
    const key =
      Blockly.Python.valueToCode(child, 'KEY', Blockly.Python.ORDER_NONE) ||
      Blockly.Python.blank
    const value =
      Blockly.Python.valueToCode(child, 'VALUE', Blockly.Python.ORDER_NONE) ||
      Blockly.Python.blank
    elements[i] = key + ': ' + value
  }
  const code = '{' + elements.join(', ') + '}'
  return [code, Blockly.Python.ORDER_ATOMIC]
}

export default Blockly
